using System;
using System.Collections.Generic;
using System.Linq;
using Granite.Modeling;
using Rifts.Models.Characters;
using Granite.DataAnnotations;

namespace Rifts.Models.Definitions
{
	//This will be used for the OCC and OCC Related skill views to append the class bonuses
	public class SkillDefinitionViewModel : SimpleModelBase
	{
		readonly SkillDefinition m_SkillDefinition;
		public SkillDefinitionViewModel(SkillType skillType, SkillDefinition skillDefinition, int? occBonus, int? fixedScore, int? perLevelOverride, int? cost)
		{
			SkillType = skillType;
			m_SkillDefinition = skillDefinition;
			OccBonus = occBonus;
			FixedScore = fixedScore;
			PerLevelOverride = perLevelOverride;
			Cost = cost ?? 1;
		}

		public SkillType SkillType
		{
			get { return Get<SkillType>("SkillType"); }
			private set { Set(value, "SkillType"); }
		}


		public int? OccBonus
		{
			get { return Get<int?>("OccBonus"); }
			private set { Set(value, "OccBonus"); }
		}

		public int IQBonus
		{
			get { return Get<int>("IQBonus"); }
			set { Set(value, "IQBonus"); }
		}

		public int Cost
		{
			get { return Get<int>("Cost"); }
			private set { Set(value, "Cost"); }
		}

		public int? FixedScore
		{
			get { return Get<int?>("FixedScore"); }
			private set { Set(value, "FixedScore"); }
		}

		public int? PerLevelOverride
		{
			get { return Get<int?>("PerLevelOverride"); }
			private set { Set(value, "PerLevelOverride"); }
		}

		public void Apply(Random random, Character character)
		{
			m_SkillDefinition.ApplySkill(SkillType,random, character, FixedScore, OccBonus, PerLevelOverride);
		}

		public bool MetRequirements
		{
			get { return Get<bool>("MetRequirements"); }
			private set { Set(value, "MetRequirements"); }
		}

		[CalculatedField("FixedScore, OccBonus, IQBonus")]
		public int? Score
		{
			get
			{
				var result = (FixedScore ?? m_SkillDefinition.BaseScore)
					+ (OccBonus ?? 0)
					+ IQBonus;

				if (result > 98)
					return 98;
				return result;
			}
		}


		public void UpdateFromCharacter(Character character, bool isOcc, int picksRemaining)
		{
			IQBonus = character.SkillBonusFromIQ;
			if (Cost > picksRemaining)
			{
				MetRequirements = false;
				return;
			}
			if (m_SkillDefinition.IsFightingStyle && character.Skills.HasHandToHand())
			{
				MetRequirements = false;
				return;
			}

			//check for a pre-existing score that is better than the proposed skill
			var preExisting = character.Skills.FindByName(Name);
			if (preExisting != null)
			{
				var newScoreIsBetter = false;

				if ((preExisting.BaseScore + (preExisting.OccBonus ?? 0)) < (m_SkillDefinition.BaseScore + (OccBonus ?? 0) + IQBonus))
					newScoreIsBetter = true;
				if (preExisting.PerLevel > (PerLevelOverride ?? m_SkillDefinition.PerLevel))
					newScoreIsBetter = true;

				if (!newScoreIsBetter)
				{
					MetRequirements = false;
					return;
				}
			}


			MetRequirements = isOcc || m_SkillDefinition.MetRequirements(character);
		}

		public string Name
		{
			get { return m_SkillDefinition.Name; }
		}

	}
}
